#include "LabyrinthGameTest.h"
#include "LabyrinthGame.h"
#include "UserInterface.h"

CPPUNIT_TEST_SUITE_REGISTRATION(LabyrinthGameTest);

void LabyrinthGameTest::testWelcome() {
	ostringstream expected;
	expected << "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
			<< "X X X X X X X " << endl
			<< "X - - - X - - " << endl
			<< "X - X - X - X " << endl
			<< "X - X * X - X " << endl
			<< "X - X X X - X " << endl
			<< "X - - - - - X " << endl
			<< "X X X X X X X " << endl
			<< "Enter your move (L=left, R-right, U=up, D=down): "
			<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testExit() {
	ostringstream expected;
	expected << "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testRestart() {
	ostringstream expected;
	expected << "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
			<< "X X X X X X X " << endl
			<< "X - - - X - - " << endl
			<< "X - X - X - X " << endl
			<< "X - X * X - X " << endl
			<< "X - X X X - X " << endl
			<< "X - - - - - X " << endl
			<< "X X X X X X X " << endl
			<< "Enter your move (L=left, R-right, U=up, D=down): "
			<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "restart" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testInvalidCommand() {
	ostringstream expected;
	expected << "Invalid command!" << endl
			<< "Enter your move (L=left, R-right, U=up, D=down): "
			<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "invalid" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testInvalidMove() {
	ostringstream expected;
	expected << "Invalid move!" << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X * X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "r" << endl
		<< "u" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveRightWithCommand_r() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - * - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveRightWithCommand_R() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - * - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "R" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}
void LabyrinthGameTest::testMoveDownWithCommand_d() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X * X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveDownWithCommand_D() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X * X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "D" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveLeftWithCommand_l() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - * - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveLeftWithCommand_L() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - * - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "L" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveUpWithCommand_u() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X * X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testMoveUpWithCommand_U() {
	ostringstream expected;
	expected << "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X * X - X " << endl
		<< "X - X - X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testWinFirstGame() {
	ostringstream expected;
	expected << "Congratulations! You escaped in 17 moves." << endl
		<< "Please enter your name for the top scoreboard: "
		<< "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X * X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testWinThirdGame() {
	ostringstream expected;
	expected << "Congratulations! You escaped in 19 moves." << endl
		<< "Please enter your name for the top scoreboard: "
		<< "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "2. player3 --> 19 moves" << endl
		<< "3. player2 --> 21 moves" << endl
		<< "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X * X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player3" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testWinFifthGame() {
	ostringstream expected;
	expected << "Congratulations! You escaped in 25 moves." << endl
		<< "Please enter your name for the top scoreboard: "
		<< "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "2. player3 --> 19 moves" << endl
		<< "3. player2 --> 21 moves" << endl
		<< "4. player1 --> 23 moves" << endl
		<< "5. player2 --> 25 moves" << endl
		<< "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X * X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player3" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testWinInTop5() {
	ostringstream expected;
	expected << "Congratulations! You escaped in 17 moves." << endl
		<< "Please enter your name for the top scoreboard: "
		<< "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "2. player4 --> 17 moves" << endl
		<< "3. player3 --> 19 moves" << endl
		<< "4. player2 --> 21 moves" << endl
		<< "5. player1 --> 23 moves" << endl
		<< "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X * X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player3" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player4" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testWinOutOfTop5() {
	ostringstream expected;
	expected << "Congratulations! You escaped in 27 moves." << endl
		<< "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "2. player3 --> 19 moves" << endl
		<< "3. player2 --> 21 moves" << endl
		<< "4. player1 --> 23 moves" << endl
		<< "5. player2 --> 25 moves" << endl
		<< "Welcome to 'Labyrinth' game. Please try to escape. Use 'top' to view the top scoreboard, "
			"'restart' to start a new game and 'exit' to quit the game." << endl
		<< "X X X X X X X " << endl
		<< "X - - - X - - " << endl
		<< "X - X - X - X " << endl
		<< "X - X * X - X " << endl
		<< "X - X X X - X " << endl
		<< "X - - - - - X " << endl
		<< "X X X X X X X " << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player3" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testTop() {
	ostringstream expected;
	expected << "Scoreboard:" << endl
		<< "1. player1 --> 17 moves" << endl
		<< "2. player3 --> 19 moves" << endl
		<< "3. player2 --> 21 moves" << endl
		<< "Enter your move (L=left, R-right, U=up, D=down): "
		<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player1" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player2" << endl
		<< "u" << endl
		<< "u" << endl
		<< "l" << endl
		<< "l" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "d" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "r" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "u" << endl
		<< "d" << endl
		<< "u" << endl
		<< "r" << endl
		<< "player3" << endl
		<< "u" << endl
		<< "top" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}

void LabyrinthGameTest::testEmptyScoreboard() {
	ostringstream expected;
	expected << "The scoreboard is empty." << endl
			<< "Enter your move (L=left, R-right, U=up, D=down): "
			<< "Good Bye!" << endl;

	const char testLabyrinth[Labyrinth::HEIGHT][Labyrinth::WIDTH] = {
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' },
		{ 'X', '-', '-', '-', 'X', '-', '-' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', '-', 'X', '-', 'X' },
		{ 'X', '-', 'X', 'X', 'X', '-', 'X' },
		{ 'X', '-', '-', '-', '-', '-', 'X' },
		{ 'X', 'X', 'X', 'X', 'X', 'X', 'X' }
	};
	*this->stimulsStream << "top" << endl
		<< "exit" << endl;
	Labyrinth labyrinth(testLabyrinth);
	LabyrinthGame labyrinthGame(labyrinth);
	labyrinthGame.play();
	string actual = this->getResult(expected.str().size());

	CPPUNIT_ASSERT_EQUAL(expected.str(), actual);
}
